package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strings"
	"time"
)

// 使用json tag指定序列化与反序列化时的行为
type Person struct {
	Name   string  `json:"name"` // 指定json序列化/反序列化时使用小写name
	Age    int64   `json:"age,omitempty"`
	Weight float64 `json:"-"` // 指定json序列化/反序列化时忽略此字段
}

func basicUseage() {
	p1 := Person{
		Name: "ybl",

		Weight: 68,
	}
	// struct -> json string
	b, err := json.Marshal(p1) //b 是[]byte类型
	if err != nil {
		fmt.Printf("json.Marshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("str:%s\n", b)
	var p2 Person
	err = json.Unmarshal(b, &p2)
	if err != nil {
		fmt.Printf("json.Unmarshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("p2:%#v\n", p2)
}

type User struct {
	Name     string   `json:"name"`
	Email    string   `json:"email,omitempty"`
	Hobby    []string `json:"hobby,omitempty"`
	Password string   `json:"password"`
	*Profile `json:"profile,omitempty"`
}
type Profile struct {
	Website string `json:"website"`
	Slogan  string `json:"slogan"`
}

func demo1() {
	u1 := User{
		Name:  "ybl",
		Hobby: []string{"games"},
	}
	b, err := json.Marshal(u1)
	if err != nil {
		fmt.Printf("json.Marshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("str:%s\n", b)
}

type PublicUser struct {
	*User              //匿名嵌套
	Password *struct{} `json:"password,omitempty"`
}

func demo2() {
	u1 := User{
		Name:     "ybl",
		Password: "123456",
	}
	b, err := json.Marshal(PublicUser{User: &u1})
	if err != nil {
		fmt.Printf("json.Marshal u1 failed, err:%v\n", err)
		return
	}
	fmt.Printf("str:%s\n", b) // str:{"name":"ybl"}
}

type Card struct {
	ID    int64   `json:"id,string"`
	Score float64 `json:"score,string"`
}

func demo3() {
	var c1 Card
	jsonStr1 := []byte(`{"id": "1234567","score": "88.50"}`)
	if err := json.Unmarshal(jsonStr1, &c1); err != nil {
		fmt.Printf("json.Unmarsha jsonStr1 failed, err:%v\n", err)
		return
	}
	fmt.Printf("c1:%#v\n", c1) // c1:main.Card{ID:1234567, Score:88.5
}
func demo4() {
	var m = make(map[string]interface{}, 1)
	m["count"] = 1
	b, err := json.Marshal(m)
	if err != nil {
		fmt.Printf("marshal failed, err:%v\n", err)
	}
	fmt.Printf("str:%#v\n", string(b))
	var m2 map[string]interface{}
	err = json.Unmarshal(b, &m2)
	if err != nil {

	}
	fmt.Printf("value:%v\n", m2["count"]) // 1
	fmt.Printf("type:%T\n", m2["count"])  // float64
}
func demo5() {
	// map[string]interface{} -> json string
	var m = make(map[string]interface{}, 1)
	m["count"] = 1 // int
	b, err := json.Marshal(m)
	if err != nil {
		fmt.Printf("marshal failed, err:%v\n", err)
	}
	fmt.Printf("str:%#v\n", string(b))
	// json string -> map[string]interface{}
	var m2 map[string]interface{}
	decoder := json.NewDecoder(bytes.NewReader(b))
	decoder.UseNumber()
	err = decoder.Decode(&m2)
	if err != nil {
		fmt.Printf("unmarshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("value:%v\n", m2["count"]) // 1
	fmt.Printf("type:%T\n", m2["count"])  // json.Number
	// 将m2["count"]转为json.Number之后调用Int64()方法获得int64类型的值
	count, err := m2["count"].(json.Number).Int64()
	if err != nil {
		fmt.Printf("parse to int64 failed, err:%v\n", err)
		return
	}
	fmt.Printf("type:%T\n", int(count)) // int
}

//func demo6()  {
//	p1:=Post{CreateTime: time.Now()}
//	b,err:=json.Marshal(p1)
//	if err != nil {
//		fmt.Printf("json.Marshal p1 failed, err:%v\n", err)
//		return
//	}
//	fmt.Printf("str:%s\n", b)
//	jsonStr:=[]byte(`{"create_time":"2020-04-05 12:25:42"}`)
//	var p2 Post
//	if err := json.Unmarshal([]byte(jsonStr), &p2); err != nil {
//		fmt.Printf("json.Unmarshal failed, err:%v\n", err)
//		return
//	}
//	fmt.Printf("p2:%#v\n", p2)
//}

type CustomTime struct {
	time.Time
}

const ctLayout = "2006-01-02 15:04:05"

var nilTime = (time.Time{}).UnixNano()

func (ct *CustomTime) UnmarshalJSON(b []byte) (err error) {
	s := strings.Trim(string(b), "\"")
	if s == "null" {
		ct.Time = time.Time{}
		return
	}
	ct.Time, err = time.Parse(ctLayout, s)
	return
}

func (ct *CustomTime) MarshalJSON() ([]byte, error) {
	if ct.Time.UnixNano() == nilTime {
		return []byte("null"), nil
	}
	return []byte(fmt.Sprintf("\"%s\"", ct.Time.Format(ctLayout))), nil
}

func (ct *CustomTime) IsSet() bool {
	return ct.UnixNano() != nilTime
}

type Post struct {
	CreateTime CustomTime `json:"create_time"`
}
type UserInfo struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func anonymousDemo() {
	u1 := UserInfo{
		ID:   123,
		Name: "YBL",
	}
	b, err := json.Marshal(struct {
		UserInfo
		Token string `json:"token"`
	}{
		u1,
		"123213",
	})
	if err != nil {
		fmt.Printf("json.Marsha failed, err:%v\n", err)
		return
	}
	fmt.Printf("str:%s\n", b)
}

type Comment struct {
	Content string
}

type Image struct {
	Title string `json:"title"`
	URL   string `json:"url"`
}

func demo7() {
	c1 := Comment{Content: "我是帅哥"}
	i1 := Image{
		Title: "图片1",
		URL:   "D://1.JPG",
	}
	b, err := json.Marshal(struct {
		Comment
		Image
	}{
		Comment: c1,
		Image:   i1,
	})
	if err != nil {
		fmt.Printf("json.Marshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("str:%s\n", b)
	// json string -> struct
	var (
		c2 Comment
		i2 Image
	)
	jsonStr := `{"Content":"content123","title":"赞赏","url":"https://1.jpg"}`
	err = json.Unmarshal([]byte(jsonStr), &struct { //这里注意是取地址符
		*Comment //这里注意要是* 否则赋值不了
		*Image
	}{
		Comment: &c2, //注意取地址符
		Image:   &i2,
	})
	if err != nil {
		fmt.Printf("json.Unmarshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("c2:%#v i2:%#v\n", c2, i2)
}

type sendMsg struct {
	User string `json:"user"`
	Msg  string `json:"msg"`
}

func rawMessageDemo() {
	jsonStr := `{"sendMsg":{"user":"ybl","msg":"加油"},"say":"Hello"}`
	var data map[string]json.RawMessage
	if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
		fmt.Printf("json.Unmarshal jsonStr failed, err:%v\n", err)
		return
	}
	var msg sendMsg
	if err := json.Unmarshal(data["sendMsg"], &msg); err != nil {
		fmt.Printf("json.Unmarshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("msg:%#v\n", msg)
}
func main() {
	//demo1()
	//demo2()
	//demo3()
	//demo4()
	//demo6()
	//anonymousDemo()
	//demo7()
	rawMessageDemo()
}
